package hu.issue.framework.web.servlet;

import hu.issue.entity.User;
import hu.issue.framework.security.SecurityContext;
import hu.issue.framework.web.Constants;
import hu.issue.framework.web.controller.Controller;
import hu.issue.framework.web.controller.RequiredRole;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class SecurityFilter implements Filter {
	private ServletContext context;

	@Override
	public void destroy() {
	}

	@Override
	public void doFilter(final ServletRequest req, final ServletResponse resp, final FilterChain chain) throws IOException, ServletException {
		final HttpServletRequest request = (HttpServletRequest) req;
		final HttpServletResponse response = (HttpServletResponse) resp;
		final ControllerMapper mapper = ContextUtil.getControllerMapper(this.context);
		final String controllerName = mapper.map(request);
		final Controller controller = ContextUtil.getControllerRegistry(this.context).getController(controllerName);
		if (controller == null) {
			response.setStatus(404);
			return;
		}

		if (!isAuthenticationRequired(controller)) {
			chain.doFilter(request, response);
			return;
		}

		final User user = SessionUtil.getUser(request.getSession());

		if (user == null) {
			request.getRequestDispatcher("login.do").forward(request, response);
			return;
		}
		
		SecurityContext.setCurrentUser(user);

		final String role = getRequiredRole(controller);
		if (!user.isInRole(role)) {
			request.getRequestDispatcher("/WEB-INF/jsp/forbidden.jsp").forward(request, response);
			return;
		}
		chain.doFilter(request, response);
	}

	private boolean isAuthenticationRequired(final Controller controller) {
		return controller.getClass().isAnnotationPresent(RequiredRole.class);
	}

	@Override
	public void init(final FilterConfig filterConfig) throws ServletException {
		this.context = filterConfig.getServletContext();
	}

	private String getRequiredRole(final Controller controller) {
		String ret = Constants.ROLE_USER;
		final Class<?> clazz = controller.getClass();
		if (clazz.isAnnotationPresent(RequiredRole.class)) {
			final RequiredRole role = clazz.getAnnotation(RequiredRole.class);
			ret = role.value();
		}

		return ret;
	}
}
